package service

import (
	"time"
	"user-center/src/common"
	"user-center/src/constant"
	"user-center/src/db"
	"user-center/src/model"
	"user-center/src/model/VO"
	"user-center/src/model/request"
	"user-center/src/model/response"

	"github.com/gin-gonic/gin"
	log "github.com/sirupsen/logrus"
)

func TeamAdd(ctx *gin.Context, team *model.Team, user *model.User) *response.BaseResponse {
	res := &response.BaseResponse{}
	if team == nil {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		return res
	}
	if user == nil {
		res.ResponseWithError(common.NOT_LOGIN, "未登录")
		return res
	}
	userId := user.Id

	// 1 队伍人数 <= 20 > 1
	maxNum := team.MaxNum
	if maxNum < 1 || maxNum > 20 {
		res.ResponseWithError(common.PARAMS_ERROR, "队伍人数不满足要求")
		return res
	}

	// 2 队伍标题 <= 20
	name := team.Name
	if name == "" || len(name) > 20 {
		res.ResponseWithError(common.PARAMS_ERROR, "队伍标题不满足要求")
		return res
	}

	// 3 描述 <= 512
	description := team.Description
	if description != "" && len(description) > 512 {
		res.ResponseWithError(common.PARAMS_ERROR, "队伍描述过长")
		return res
	}

	// 4 status 是否公开（int) 不传默认为0（公开）
	status := team.Status
	if status != constant.TEAMSECRET && status != constant.TEAMPRIVATE {
		status = constant.TEAMPUBLIC
	}

	// 5 如果status是加密状态，要有密码 密码 <= 32
	password := team.Password
	if status == constant.TEAMSECRET {
		if password == "" || len(password) > 32 {
			res.ResponseWithError(common.PARAMS_ERROR, "密码设置不正确")
			return res
		}
	}

	// 6 超时时间 > 当前时间
	expireTime := team.ExpireTime
	if time.Now().After(expireTime) {
		res.ResponseWithError(common.PARAMS_ERROR, "超时时间大于当前时间")
		return res
	}

	// 7 校验用户最多5个队伍
	var count int64
	if err := db.GetMySQL().Model(&model.Team{}).Where("userId = ? and isDelete = 0", userId).Count(&count).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "未知错误")
		return res
	}
	if count >= 5 {
		res.ResponseWithError(common.PARAMS_ERROR, "用户最多创建5个队伍")
		return res
	}

	// 8 插入到队伍表
	team.Id = 0
	team.UserId = userId
	team.CreateTime = time.Now()
	team.UpdateTime = time.Now()
	if err := db.GetMySQL().Create(team).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "创建失败")
		return res
	}

	// 9 插入用户 => 队伍关系到关系表
	userTeam := &model.UserTeam{
		UserId:     userId,
		TeamId:     team.Id,
		JoinTime:   time.Now(),
		CreateTime: time.Now(),
		UpdateTime: time.Now(),
	}
	if err := db.GetMySQL().Create(userTeam).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "创建失败")
		return res
	}
	res.ResponseWithData(team.Id)
	return res
}

func UpdateTeam(ctx *gin.Context, reqTeam *request.TeamUpdateRequest, currentUser *model.User) *response.BaseResponse {
	res := &response.BaseResponse{}

	teamId := reqTeam.Id
	if teamId <= 0 {
		log.Warningf("get user info error")
		res.ResponseWithError(common.PARAMS_ERROR, "用户错误")
		return res
	}
	oldTeam := getTeamByIdModel(teamId)
	if oldTeam == nil {
		log.Warningf("get team info error")
		res.ResponseWithError(common.PARAMS_ERROR, "队伍错误")
		return res
	}
	// 仅管理员和队长可以修改
	if !IsAdmin(ctx) && oldTeam.UserId != currentUser.Id {
		log.Warningf("Non authr")
		res.ResponseWithError(common.NO_AUTH, "无权限")
		return res
	}
	// 修改队伍加密状态下还要有密码
	if oldTeam.Status == constant.TEAMSECRET && reqTeam.Status == constant.TEAMSECRET && reqTeam.Password == "" {
		res.ResponseWithError(common.PARAMS_ERROR, "需输入密码")
		return res
	}
	newTeam := oldTeam
	if reqTeam.Name != "" {
		newTeam.Name = reqTeam.Name
	}
	if !reqTeam.ExpireTime.IsZero() {
		newTeam.ExpireTime = reqTeam.ExpireTime
	}
	if reqTeam.Description != "" {
		newTeam.Description = reqTeam.Description
	}
	if reqTeam.Password != "" {
		newTeam.Password = reqTeam.Password
	}

	db.GetMySQL().Model(newTeam).Updates(newTeam)
	res.ResponseSuccess()
	return res
}
func GetTeamById(ctx *gin.Context, id int64) *response.BaseResponse {
	team := getTeamByIdModel(id)
	res := &response.BaseResponse{}
	if team == nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "没有查到队伍信息")
		return res
	}
	res.ResponseWithData(team)
	return res
}
func getTeamByIdModel(id int64) *model.Team {
	if id <= 0 {
		return nil
	}
	team := &model.Team{}
	result := db.GetMySQL().First(team, id)
	if result.Error == nil && result.RowsAffected == 1 {
		return team
	}
	return nil
}

// 默认一页20队伍
func ListTeams(ctx *gin.Context, teamQuery *request.TeamQuery, isAdmin bool) *response.BaseResponse {
	var teamUserVOList []VO.TeamUserVO
	res := &response.BaseResponse{}
	if teamQuery.PageNum < 1{
		teamQuery.PageNum = 1
	}
	if teamQuery.PageSize <= 0{
		teamQuery.PageSize = 20
	}
	queryDb := db.GetMySQL().Debug()

	if teamQuery != nil {
		if len(teamQuery.IdList) > 0 {
			queryDb = queryDb.Where("id IN (?)", teamQuery.IdList)
		}
		if teamQuery.SearchText != "" {
			searchText := "%" + teamQuery.SearchText + "%"
			queryDb = queryDb.Where("name LIKE ? OR description LIKE ?", searchText, searchText)
		}
		if teamQuery.Name != "" {
			queryDb = queryDb.Where("name LIKE ?", "%"+teamQuery.Name+"%")
		}
		if teamQuery.Description != "" {
			queryDb = queryDb.Where("description LIKE ?", "%"+teamQuery.Description+"%")
		}
		if teamQuery.MaxNum > 0 {
			queryDb = queryDb.Where("maxNum = ?", teamQuery.MaxNum)
		}
		if teamQuery.UserId > 0 {
			queryDb = queryDb.Where("userId = ?", teamQuery.UserId)
		}

		// 如果不是管理员 并且还没设置状态 默认公开 ，是管理员的话查全部
		// 管理员查全部  非管理员只能查看 【加密，公开，自己加入的隐藏】 没登陆用户只能查看【加密，公开】
		user := GetUserCurrentInfo(ctx)
		if user == nil {
			user = &model.User{
				Id: -1,
			}
		}
		if teamQuery.Status != constant.TEAMPRIVATE && teamQuery.Status != constant.TEAMUNKNOW {
			queryDb = queryDb.Where("status = ?", teamQuery.Status)
		} else if !IsAdmin(ctx) {
			if teamQuery.Status == constant.TEAMPRIVATE {
				queryDb = queryDb.Where("status = ? and userId = ? ", teamQuery.Status, user.Id)
			} else if teamQuery.Status == constant.TEAMUNKNOW {
				queryDb = queryDb.Where("status != ? or userId = ? ", constant.TEAMPRIVATE, user.Id)
			}
		}

		{
			queryDb = queryDb.Where("isDelete = 0")
		}
	}
	// 不展示已过期队伍
	queryDb = queryDb.Where("expireTime > ? or expireTime IS NULL ", time.Now())
	
	// 分页查询第几页
	queryDb = queryDb.Offset((teamQuery.PageNum  - 1)* teamQuery.PageSize).Limit(teamQuery.PageSize)

	var list []model.Team
	if err := queryDb.Find(&list).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "数据未知错误")
		return res
	}

	// 关联查询创建人的用户信息
	for _, team := range list {
		if team.UserId == 0 {
			continue
		}
		user := &model.User{}
		db.GetMySQL().First(user, team.UserId)
		teamUserVO := &VO.TeamUserVO{
			Id:          team.Id,
			Name:        team.Name,
			Description: team.Description,
			MaxNum:      team.MaxNum,
			ExpireTime:  team.ExpireTime,
			UserId:      team.UserId,
			Status:      team.Status,
			CreateTime:  team.CreateTime,
			UpdateTime:  team.UpdateTime,
		}
		var userVO *VO.UserVO
		if user.Id != 0 {
			userVO = &VO.UserVO{
				Id:          user.Id,
				Username:    user.Username,
				UserAccount: user.UserAccount,
				AvatarUrl:   user.AvatarUrl,
				Gender:      user.Gender,
				Phone:       user.Phone,
				Email:       user.Email,
				UserStatus:  user.UserStatus,
				CreateTime:  user.CreateTime,
				UpdateTime:  user.UpdateTime,
				UserRole:    user.UserRole,
				Tags:        user.Tags,
				Profile:     user.Profile,
			}
		}
		teamUserVO.CreateUser = userVO
		teamUserVOList = append(teamUserVOList, *teamUserVO)
	}
	res.ResponseWithData(teamUserVOList)
	return res
}

func ListTeamsJoinInMy(ctx *gin.Context, teamQuery *request.TeamQuery, currentUser *model.User) *response.BaseResponse {
	res := &response.BaseResponse{}
	if teamQuery == nil || currentUser == nil {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		return res
	}
	var userTeamList []model.UserTeam
	if err := db.GetMySQL().Where("userId = ? and isDelete = 0", currentUser.Id).Find(&userTeamList).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "数据未知错误")
		return res
	}
	if len(userTeamList) == 0 {
		return res
	}
	teamquery := &request.TeamQuery{}
	for _, i := range userTeamList {
		teamquery.IdList = append(teamquery.IdList, i.TeamId)
	}
	return ListTeams(ctx, teamquery, true)
}

func JoinTeam(ctx *gin.Context, req *request.TeamJoinRequest, currentUser *model.User) *response.BaseResponse {
	res := &response.BaseResponse{}
	if req == nil {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		return res
	}
	if currentUser == nil {
		res.ResponseWithError(common.NOT_LOGIN, "未登录")
		return res
	}

	teamId := req.TeamId
	team := getTeamByIdModel(teamId)
	if team == nil {
		res.ResponseWithError(common.PARAMS_ERROR, "没有该队伍")
		return res
	}
	now := time.Now()
	if !team.ExpireTime.IsZero() && team.ExpireTime.Before(now) {
		res.ResponseWithError(common.NULL_ERROR, "队伍以过期")
		return res
	}

	if team.Status == constant.TEAMPRIVATE {
		res.ResponseWithError(common.NULL_ERROR, "禁止加入私有队伍")
		return res
	}

	password := req.Password
	if team.Status == constant.TEAMSECRET && password != team.Password {
		res.ResponseWithError(common.NULL_ERROR, "密码错误")
		return res
	}
	userId := currentUser.Id

	//todo 大锁 防止一个用户同时加入超过限制
	constant.Mutex.Lock()
	defer constant.Mutex.Unlock()
	var userTeamCount int64
	// 查询用户已加入的队伍数量
	if err := db.GetMySQL().Model(&model.UserTeam{}).Where("userId = ? and isDelete = 0", userId).Count(&userTeamCount).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "系统错误")
		return res
	}
	if userTeamCount > 5 {
		res.ResponseWithError(common.NULL_ERROR, "最多创建或加入5个队伍")
		return res
	}
	var hasJoined int64
	// 检查是否已经加入了该队伍
	if err := db.GetMySQL().Model(&model.UserTeam{}).Where("userId = ? AND teamId = ? and isDelete = 0", userId, teamId).Count(&hasJoined).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "系统错误")
		return res
	}
	if hasJoined > 0 {
		res.ResponseWithError(common.NULL_ERROR, "用户已加入了")
		return res
	}
	var teamHasJoinNum int64
	// 查询已加入队伍的人数
	if err := db.GetMySQL().Model(&model.UserTeam{}).Where("teamId = ? and isDelete = 0", teamId).Count(&teamHasJoinNum).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "系统错误")
		return res
	}
	if int(teamHasJoinNum) > team.MaxNum {
		res.ResponseWithError(common.SYSTEM_ERROR, "队伍已满")
		return res
	}

	// 修改队伍信息
	userTeam := &model.UserTeam{
		UserId:   userId,
		TeamId:   teamId,
		JoinTime: time.Now(),
	}
	if err := db.GetMySQL().Select("userId", "teamId", "joinTime").Create(userTeam).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "加入错误")
		return res
	}

	res.ResponseWithData("加入成功 ， 有新组织啦")
	return res
}

func DeleteTeam(ctx *gin.Context, req *request.TeamDeleteRequest, currentUser *model.User) *response.BaseResponse {
	res := &response.BaseResponse{}
	if req == nil {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		return res
	}
	if currentUser == nil {
		res.ResponseWithError(common.NOT_LOGIN, "未登录")
		return res
	}
	// 校验是否是队长
	team := &model.Team{}
	tx := db.GetMySQL().Begin()
	if err := tx.First(team, "isDelete = 0 and id = ? and userId = ?", req.TeamId, currentUser.Id).Error; err != nil {
		res.ResponseWithError(common.NO_INFO, "你没有创建这个队伍")
		tx.Rollback()
		return res
	}
	//删除队伍信息
	if err := tx.Model(&model.Team{}).Where("id = ?", req.TeamId).Update("isDelete", 1).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "没有队伍")
		tx.Rollback()
		return res
	}

	//移除队伍成员
	if err := tx.Model(&model.UserTeam{}).Where("teamId = ? and isDelete = 0", req.TeamId).Update("isDelete", 1).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "没有成员")
		tx.Rollback()
		return res
	}

	tx.Commit()
	return res
}
func QuitTeam(ctx *gin.Context, req *request.TeamQuitRequest, currentUser *model.User) *response.BaseResponse {
	res := &response.BaseResponse{}
	if req == nil {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		return res
	}
	if currentUser == nil {
		res.ResponseWithError(common.NOT_LOGIN, "未登录")
		return res
	}
	team := &model.Team{}
	if err := db.GetMySQL().First(team, "id = ?", req.TeamId).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "队伍查询错误")
		return res
	}
	// 队长退出 就是解散
	if team.UserId == currentUser.Id {
		return DeleteTeam(ctx, &request.TeamDeleteRequest{TeamId: team.Id}, currentUser)
	}
	if err := db.GetMySQL().Model(model.UserTeam{}).Where("isDelete = 0 and teamId = ? and userId = ?", req.TeamId, currentUser.Id).Update("isDelete", 1).Error; err != nil {
		res.ResponseWithError(common.SYSTEM_ERROR, "退出未知错误")
		return res
	}
	return res
}
